package com.zz.hhbl.utils

import android.annotation.SuppressLint
import android.content.Context
import android.media.AudioFormat
import android.media.AudioRecord
import android.media.MediaRecorder
import android.util.Base64
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.io.ByteArrayOutputStream
import java.io.IOException

/**
 * Copyright © 2025 zhun All rights reserved.
 * Created by ZhaoZhun on 2025/3/4 14:38.
 * @author: ZhaoZhun 1820022519@qq.com
 * @version: V1.0
 */
class AudioRecorderManager private constructor() {
    companion object {
        // 音频采样率，固定为 16000Hz
        private const val SAMPLE_RATE = 16000
        // 音频通道配置，单声道
        private const val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO
        // 音频数据格式，16 位 PCM 格式
        private const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
        // 每 10 秒的音频数据长度
        private const val TEN_SECONDS_LENGTH = SAMPLE_RATE * 2 * 10 // 采样率 * 采样位宽（2 字节） * 10 秒

        @Volatile
        private var instance: AudioRecorderManager? = null

        fun getInstance(): AudioRecorderManager {
            return instance ?: synchronized(this) {
                instance ?: AudioRecorderManager().also { instance = it }
            }
        }
    }

    // 缓冲区大小
    private val bufferSize: Int = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT)
    // AudioRecord 对象
    private var audioRecord: AudioRecord? = null
    // 录音状态
    private var isRecording = false
    // 音频数据缓冲区
    private val buffer = ByteArray(bufferSize)
    // 协程作用域
    private var recordingJob: Job? = null
    // 用于存储 10 秒音频数据的输出流
    private var audioDataOutputStream: ByteArrayOutputStream? = null
    // 回调接口
    private var audioCallback: ((String) -> Unit)? = null

    /**
     * 设置音频数据回调
     * @param callback 回调函数，接收 Base64 编码的音频数据
     */
    fun setAudioCallback(callback: (String) -> Unit) {
        this.audioCallback = callback
    }

    /**
     * 开始录音
     */
    fun startRecording() {
        if (isRecording) return
        if (audioRecord == null) {
            reinitializeAudioRecord()
        }
        audioRecord?.startRecording()
        isRecording = true
        audioDataOutputStream = ByteArrayOutputStream()
        recordingJob = CoroutineScope(Dispatchers.IO).launch {
            try {
                while (isRecording) {
                    val read = audioRecord?.read(buffer, 0, bufferSize) ?: 0
                    if (read > 0) {
                        audioDataOutputStream?.write(buffer, 0, read)
                        if (audioDataOutputStream?.size() ?: 0 >= TEN_SECONDS_LENGTH) {
                            val audioData = audioDataOutputStream?.toByteArray()
                            val base64Audio = Base64.encodeToString(audioData, Base64.DEFAULT)
                            audioCallback?.invoke(base64Audio)
                            audioDataOutputStream?.reset()
                        }
                    }
                }
                // 处理最后不足 10 秒的音频数据
                val remainingAudioData = audioDataOutputStream?.toByteArray()
                if (remainingAudioData?.isNotEmpty() == true) {
                    val base64Audio = Base64.encodeToString(remainingAudioData, Base64.DEFAULT)
                    audioCallback?.invoke(base64Audio)
                }
            } catch (e: IOException) {
                Log.e("AudioRecorderManager", "录音过程中出现错误", e)
            } finally {
                releaseAudioRecord()
            }
        }
    }

    /**
     * 停止录音
     */
    fun stopRecording() {
        if (!isRecording) return
        isRecording = false
        recordingJob?.cancel()
    }

    /**
     * 判断是否正在录音
     * @return 如果正在录音返回 true，否则返回 false
     */
    fun isRecording(): Boolean {
        return isRecording
    }

    /**
     * 释放 AudioRecord 资源
     */
    private fun releaseAudioRecord() {
        audioRecord?.stop()
        audioRecord?.release()
        audioRecord = null
        audioDataOutputStream?.close()
        audioDataOutputStream = null
    }

    /**
     * 清理资源，在不需要使用该管理器时调用
     */
    fun cleanUp() {
        stopRecording()
        releaseAudioRecord()
        recordingJob = null
        audioCallback = null
    }

    /**
     * 重新初始化 AudioRecord 对象
     */
    @SuppressLint("MissingPermission")
    private fun reinitializeAudioRecord() {
        audioRecord = AudioRecord(
            MediaRecorder.AudioSource.MIC,
            SAMPLE_RATE,
            CHANNEL_CONFIG,
            AUDIO_FORMAT,
            bufferSize
        )
    }
}